#include <linux/module.h>
#include <linux/fs.h>          // file_operations
#include <linux/cdev.h>        // cdev
#include <linux/device.h>      // class_create, device_create
#include <linux/uaccess.h>     // copy_to_user, copy_from_user
#include <linux/errno.h>       // 错误码宏定义
#include <linux/slab.h>        // kmalloc/kfree (如果需要动态内存)

#define DEVICE_NAME "my_char_dev"
#define BUFFER_SIZE 1024

static dev_t dev; //使用dev_t类型
static int major;              // 主设备号（动态分配）
static struct class *my_class;
static struct cdev my_cdev;

// 设备缓冲区（用于读写测试）
static char device_buffer[BUFFER_SIZE];

// ------------------------------
// 1. 实现 file_operations 操作函数
// ------------------------------
static int my_open(struct inode *inode, struct file *filp) {
    printk(KERN_INFO "Device opened\n");
    return 0;
}

static ssize_t my_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {
	size_t bytes_avail, bytes_to_copy;  // 声明放在函数开头
	
    // 检查偏移量是否超出缓冲区范围
    if (*f_pos >= BUFFER_SIZE) {
        return 0; // 文件末尾
    }

    // 计算可读取字节数
    bytes_avail = BUFFER_SIZE - (size_t)*f_pos;
    bytes_to_copy = min_t(size_t, count, bytes_avail);

    // 数据拷贝到用户空间
    if (copy_to_user(buf, device_buffer + (size_t)*f_pos, bytes_to_copy)) {
        return -EFAULT;
    }

    *f_pos += bytes_to_copy;
    return bytes_to_copy;
}

static ssize_t my_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
	size_t space_avail, bytes_to_copy;  // 声明放在函数开头
	
    // 检查偏移量是否超出缓冲区限制
    if (*f_pos >= BUFFER_SIZE) {
        return -EFBIG; // 文件过大
    }

    // 计算可写入空间
    space_avail = BUFFER_SIZE - (size_t)*f_pos;
    bytes_to_copy = min_t(size_t, count, space_avail);

    // 数据拷贝到内核缓冲区
    if (copy_from_user(device_buffer + (size_t)*f_pos, buf, bytes_to_copy)) {
        return -EFAULT;
    }

    *f_pos += bytes_to_copy;
    return bytes_to_copy;
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .read = my_read,
    .write = my_write,
};

// ------------------------------
// 2. 完整的模块初始化函数
// ------------------------------
static int __init my_init(void) {
    int ret = 0;

    // 1. 动态分配主设备号
    ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
    if (ret < 0) {
        printk(KERN_ERR "Failed to allocate char device region\n");
        goto fail;
    }
	major = MAJOR(dev);  //从dev_t中提取主设备号
    printk(KERN_INFO "Allocated major number: %d\n", major);

    // 2. 创建设备类（sysfs中可见）
    my_class = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(my_class)) {
        ret = PTR_ERR(my_class);
        printk(KERN_ERR "Failed to create device class\n");
        goto unregister_region;
    }

    // 3. 初始化并添加cdev结构
    cdev_init(&my_cdev, &fops);
    my_cdev.owner = THIS_MODULE;
    ret = cdev_add(&my_cdev, MKDEV(major, 0), 1);
    if (ret < 0) {
        printk(KERN_ERR "Failed to add cdev\n");
        goto destroy_class;
    }

    // 4. 创建设备节点（/dev/my_char_dev）
    device_create(my_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
    printk(KERN_INFO "Device created: /dev/%s\n", DEVICE_NAME);

    // 初始化设备缓冲区
    memset(device_buffer, 0, BUFFER_SIZE);
    return 0;

// 错误处理（逆序清理资源）
destroy_class:
    class_destroy(my_class);
unregister_region:
    unregister_chrdev_region(major, 1);
fail:
    return ret;
}

// ------------------------------
// 3. 完整的模块退出函数
// ------------------------------
static void __exit my_exit(void) {
    // 1. 销毁设备节点
    device_destroy(my_class, MKDEV(major, 0));

    // 2. 删除cdev
    cdev_del(&my_cdev);

    // 3. 销毁设备类
    class_destroy(my_class);

    // 4. 释放设备号
    unregister_chrdev_region(major, 1);

    printk(KERN_INFO "Device driver unloaded\n");
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver");
MODULE_VERSION("0.1");